/*
* compile codes for server-side rendering,
* transform file directly using babel, remain the directory structure
* only transform jsx grammar, es modules, decorators, nothing else because the source has been already nodejs runable
* if you use some complex grammars (decorators, import, fuck)
*/
import del from 'del'
import gulp from 'gulp'
import * as through2 from 'through2'
import * as babel from '@babel/core'

import PROJECT from '../PROJECT'

const BABEL_CONFIG = {
  presets: [
    require('@babel/preset-flow'),
    require('@babel/preset-react'),
    require('@babel/preset-env'),
  ],
  plugins: [
    require('@babel/plugin-syntax-dynamic-import'),
    require('@loadable/babel-plugin'),
  ],
}

// const IS_CLIENT_VARIABLE = '__IS_CLIENT__'
// const REQUIRE_PATH_FUNCTION = '__requirePublicPath__'

// const replaceRequireFile = str => {
//   const pattern = /(require *\( *)(('|").*\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)('|"))( *\) *)/g   /* \r\n in windows, \n in unix */
//   const newstr = str.replace(pattern, (match, requireWord, fileName) => {
//     return `(${IS_CLIENT_VARIABLE} ? require(${fileName}) : ${REQUIRE_PATH_FUNCTION}(__dirname, ${fileName}))`
//   })
//   return newstr
// }

// const replaceRequireCss = str => {
//   const pattern = /(import +|require *\( *)(('|").*\.(css|less)('|"))( *\)* *)/g
//   const newstr = str.replace(pattern, (match, requireWord, fileName) => {
//     return `if (${IS_CLIENT_VARIABLE}) { require(${fileName}) }`
//   })
//   return newstr
// }

const isomorphicCode = 
`

if (typeof __ssr_isomorphic_tools__ === 'object') {
  require = __ssr_isomorphic_tools__.createRequire(require, __dirname)
}

`

const addIsomorphicCode = str => str.replace('\n', isomorphicCode)

const clean = () => del([PROJECT.BUILD.ROOT], { force: true })

const compileScripts = () => (
  gulp
  .src([`${PROJECT.SRC.ROOT}/**/*.js`])
  .pipe(
    through2.obj((file, enc, cb) => {
      babel.transform(file.contents.toString(), BABEL_CONFIG, (err, result) => {
        if (err) { cb(err); return }
        const str = addIsomorphicCode(result.code)
        file.contents = Buffer.from(str)
        cb(null, file)
      })
    })
  )
  .pipe(gulp.dest(PROJECT.BUILD.ROOT))
)

const compileNonScripts = () => (
  gulp
  .src([`${PROJECT.SRC.ROOT}/**/*.*`, `!${PROJECT.SRC.ROOT}/**/*.js`])
  .pipe(gulp.dest(PROJECT.BUILD.ROOT))
)

const run = () => new Promise((ok, fail) => (
  gulp.series(
    clean,
    gulp.parallel(compileScripts, compileNonScripts),
  )(err => err ? fail(err) : ok())
))

const watch = () => gulp.watch(`${PROJECT.SRC.ROOT}/**/*.js`, run)

export default () => run()
  .then(() => console.log('BUILD OK'))
  .catch(console.log)
